package com.ruoyi.system.service.impl;

import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.domain.GloryDataDTO;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.domain.GloryData;
import com.ruoyi.system.domain.GloryType;
import com.ruoyi.system.mapper.GloryTypeMapper;
import com.ruoyi.system.service.IGloryTypeService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 荣誉类型Service业务层处理
 *
 * @author 王清江
 * @date 2021-01-29
 */
@Service
public class GloryTypeServiceImpl implements IGloryTypeService {
    @Autowired
    private GloryTypeMapper gloryTypeMapper;

    @Autowired
    private RedisCache redisCache;

    /**
     * 初始化，将荣誉类型、荣誉数据存入redis，数据预热
     */
    @Override
    @PostConstruct
    public List<GloryType> init() {
        //先清空redis中的荣誉类型，方便即将重新进行输入redis
        boolean successFlag = redisCache.deleteObject(Constants.SYS_GLORY_TYPE_KEY);
        //请注意，下面的Constants.SYS_GLORY_DATA_KEY仅仅是返回前端的那个每次都一样一样的东西。
        boolean successFlag2 = redisCache.deleteObject(Constants.SYS_GLORY_DATA_KEY);
        System.out.println("荣誉类型TYPE:" + successFlag + " \n荣誉数据DATA:"
                + successFlag2 + "--->若是false，则说明redis中的本来就没有数据，请不必担心");
        //数据库查询荣誉类型
        List<GloryType> gloryTypes = selectGloryTypeList(null);
        //流式计算，让荣誉类型的gloryDataList进行填充
        List<GloryType> gloryTypeList = gloryTypes.stream()
                .map(gloryType -> selectGloryTypeById(gloryType.getGloryTypeId()))
                .collect(Collectors.toList());
        //各个击破存入redis
        gloryTypeList.forEach(gloryType -> {
            redisCache.setCacheObject(Constants.SYS_GLORY_TYPE_KEY + gloryType.getGloryTypeId(), gloryType);
            //顺便把荣誉data一块存进去吧！迭代每一个type，让里面的数据再次迭代
            List<GloryData> gloryDataList = gloryType.getGloryDataList();
            gloryDataList.forEach(gloryData -> {
                redisCache.setCacheObject(Constants.SYS_GLORY_DATA_KEY + gloryData.getGloryId(), gloryData);
            });
        });
        //一次性存入总的redis
        redisCache.setCacheList(Constants.SYS_GLORY_TYPE_KEY, gloryTypeList);
        return gloryTypeList;
    }

    /**
     * 前端需要的荣誉数据，直接在缓存中取
     *
     * @return 荣誉数据集
     */
    @Override
    public List<GloryDataDTO> getGloryData() {
        //先去redis中取，取不到在执行init方法重新填充
        List<GloryDataDTO> gloryDataDTOList = redisCache.getCacheList(Constants.SYS_GLORY_DATA_KEY);
        if (gloryDataDTOList == null || gloryDataDTOList.size() == 0) {
            gloryDataDTOList = initGloryData();
        }
        return gloryDataDTOList;
    }

    /**
     * 从缓存中拿到相关的值，根据荣誉数据Id查询
     *
     * @return 荣誉数据
     */
    @Override
    public GloryData getGloryDataFromCache(Long gloryId) {
        //掏出缓存查询
        GloryData gloryData = redisCache.getCacheObject(Constants.SYS_GLORY_DATA_KEY + gloryId);
        if (gloryData == null) {
            //从数据查询，并且填充缓存
            gloryData = gloryTypeMapper.selectGloryDataById(gloryId);
            redisCache.setCacheObject(Constants.SYS_GLORY_DATA_KEY + gloryId, gloryData);
        }
        return gloryData;
    }

    /**
     * 这里是数据预热 荣誉data
     *
     * @return glory data list
     */
    @PostConstruct
    public List<GloryDataDTO> initGloryData() {
        List<GloryType> cacheList = redisCache.getCacheList(Constants.SYS_GLORY_TYPE_KEY);
        if (cacheList == null || cacheList.size() == 0) {
            cacheList = init();
        }
        //从数据库或者是缓存取到了数据之后，现在开始封装成GloryDataDTO，外层是类型，内层才是真实的
        List<GloryDataDTO> gloryDataDTOList = new ArrayList<GloryDataDTO>();
        cacheList.stream().forEach(gloryType -> {
            //拿到每一个gloryType进行迭代，外层是label，就够了吧，内层需要value和label
            GloryDataDTO gloryDataDTO = new GloryDataDTO();
            gloryDataDTO.setLabel(gloryType.getGloryTypeName());
            List<GloryData> gloryDataList = gloryType.getGloryDataList();
            List<GloryDataDTO> gloryDataDtoArrayList = new ArrayList<GloryDataDTO>();
            gloryDataList.stream().forEach(gloryData -> {
                //迭代，将数据包装到DTO中的list中
                GloryDataDTO gloryDataDTO1 = new GloryDataDTO();
                gloryDataDTO1.setLabel(gloryData.getGloryLabel());
                //这里这个value值是前端需要的gloryId 荣誉ID
                gloryDataDTO1.setValue(gloryData.getGloryId());
                gloryDataDtoArrayList.add(gloryDataDTO1);
            });
            gloryDataDTO.setChildren(gloryDataDtoArrayList);
            gloryDataDTOList.add(gloryDataDTO);
        });
        //把这些数据存入redis，然后每次来取，就不需要每次进行一次流式计算了
        redisCache.setCacheList(Constants.SYS_GLORY_DATA_KEY, gloryDataDTOList);
        return gloryDataDTOList;
    }


    /**
     * 查询荣誉类型
     *
     * @param gloryTypeId 荣誉类型ID
     * @return 荣誉类型
     */
    @Override
    public GloryType selectGloryTypeById(Long gloryTypeId) {
        GloryType gloryType = gloryTypeMapper.selectGloryTypeById(gloryTypeId);
        return gloryType;
    }

    /**
     * 查询荣誉类型列表
     *
     * @param gloryType 荣誉类型
     * @return 荣誉类型
     */
    @Override
    public List<GloryType> selectGloryTypeList(GloryType gloryType) {
        return gloryTypeMapper.selectGloryTypeList(gloryType);
    }

    /**
     * 新增荣誉类型
     *
     * @param gloryType 荣誉类型
     * @return 结果
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public int insertGloryType(GloryType gloryType) {
        gloryType.setCreateTime(DateUtils.getNowDate());
        //方恒-王清江  添加创建者~
        gloryType.setCreateBy(SecurityUtils.getUsername());
        int rows = gloryTypeMapper.insertGloryType(gloryType);
        insertGloryData(gloryType);
        return rows;
    }

    /**
     * 修改荣誉类型
     *
     * @param gloryType 荣誉类型
     * @return 结果
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public int updateGloryType(GloryType gloryType) {
        gloryType.setUpdateTime(DateUtils.getNowDate());
        //王清江增加修改人
        gloryType.setUpdateBy(SecurityUtils.getUsername());
        gloryTypeMapper.deleteGloryDataByGloryTypeId(gloryType.getGloryTypeId());
        insertGloryData(gloryType);
        return gloryTypeMapper.updateGloryType(gloryType);
    }

    /**
     * 批量删除荣誉类型
     *
     * @param gloryTypeIds 需要删除的荣誉类型ID
     * @return 结果
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public int deleteGloryTypeByIds(Long[] gloryTypeIds) {
        gloryTypeMapper.deleteGloryDataByGloryTypeIds(gloryTypeIds);
        return gloryTypeMapper.deleteGloryTypeByIds(gloryTypeIds);
    }

    /**
     * 删除荣誉类型信息
     *
     * @param gloryTypeId 荣誉类型ID
     * @return 结果
     */
    @Override
    public int deleteGloryTypeById(Long gloryTypeId) {
        gloryTypeMapper.deleteGloryDataByGloryTypeId(gloryTypeId);
        return gloryTypeMapper.deleteGloryTypeById(gloryTypeId);
    }

    /**
     * 修改荣誉类型状态
     *
     * @param gloryType 荣誉类型
     * @return 影响行数
     */
    @Override
    public int updateGloryStatus(GloryType gloryType) {
        return gloryTypeMapper.updateGloryType(gloryType);
    }

    /**
     * 刷新用户看到的荣誉类型缓存
     */
    @Override
    public void flushCache() {
        init();
    }

    /**
     * 新增荣誉数据信息
     *
     * @param gloryType 荣誉类型对象
     */
    public void insertGloryData(GloryType gloryType) {
        List<GloryData> gloryDataList = gloryType.getGloryDataList();
        Long gloryTypeId = gloryType.getGloryTypeId();
        if (StringUtils.isNotNull(gloryDataList)) {
            List<GloryData> list = new ArrayList<GloryData>();
            for (GloryData gloryData : gloryDataList) {
                gloryData.setCreateBy(SecurityUtils.getUsername());
                gloryData.setGloryTypeId(gloryTypeId);
                list.add(gloryData);
            }
            if (list.size() > 0) {
                gloryTypeMapper.batchGloryData(list);
            }
        }
    }
}
